package com.example.core.service;

import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.example.core.dao.BaseTreeDao;
import com.example.core.debezium.listener.SysDebeziumDataChangeListener;
import com.example.core.debezium.message.Message;
import com.example.core.mapping.Mapping;
import com.example.core.po.BaseTreePo;
import com.example.core.vo.BaseTreeVo;
import com.example.sys.module.po.SysModule;
import com.example.sys.module.service.SysModuleService;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


/***
 * 树形结构的基类，当用户改变数据的时候，考虑到需要重新刷新缓存数据，
 * @param <M>
 * @param <T>
 * @param <V>
 */
public class BaseTreeServiceImpl<M extends BaseTreeDao<T>, T extends BaseTreePo, V extends BaseTreeVo> extends BaseServiceImpl<M, T, V> implements BaseTreeService<T, V>, SysDebeziumDataChangeListener {

    public static final String TREECACHE = "treeCache";

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public Class<? extends Mapping> getMappingClass() {
        return null;
    }

    @Override
    public List<T> findRoot(HttpServletRequest request, HttpServletResponse response) {
        return getBaseMapper().findRoot();
    }

    @Override
    public List<T> findByPId(Serializable pid) {
        return getBaseMapper().findByPId(pid);
    }

    @Override
    public T buildTree(T po) {
        List<T> sysTrees = this.findByPId(po.getId());
        po.getChildren().addAll(sysTrees);
        for (T tree : sysTrees) {
            buildTree(tree);
        }
        return po;
    }

    @Override
    public List<T> findTreeList(HttpServletRequest request, HttpServletResponse response) {
        List<T> trees = new ArrayList<>();
        List<T> roots = this.findRoot(request, response);
        for (T root : roots) {
            this.buildTree(root);
            trees.add(root);
        }
        return trees;
    }

    /***
     * 数据监听，如果改变了树形结构数据，那么就需要主动刷新缓存的。
     * @param message
     */
    @Override
    public void changeEvent(Message message) {
        if (message.getHandleType().equalsIgnoreCase(Message.CREATE) || message.getHandleType().equalsIgnoreCase(Message.UPDATE)) {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(message.getTable());
            if (tableInfo != null && BaseTreePo.class.isAssignableFrom(tableInfo.getEntityType())) {
                SysModuleService sysModuleService = getApplicationContext().getBean(SysModuleService.class);
                SysModule sysModule = sysModuleService.getModuleByPo(tableInfo.getEntityType().getName());
                if (sysModule != null) {
                    redisTemplate.delete(TREECACHE + "::" + sysModule.getService());
                }
            }
        }
    }
}
